soft-reboot: Check for kernel argument changes
authorColin Walters <walters@verbum.org>
Wed, 9 Jul 2025 19:21:56 +0000 (15:21 -0400)
committerColin Walters <walters@verbum.org>
Wed, 9 Jul 2025 19:34:35 +0000 (15:34 -0400)
This closes a drift gap possibility.

Signed-off-by: Colin Walters <walters@verbum.org>
src/libostree/ostree-deployment-private.h
src/libostree/ostree-deployment.c
src/libostree/ostree-deployment.h
src/libostree/ostree-kernel-args-private.h
src/libostree/ostree-kernel-args.c
src/libostree/ostree-kernel-args.h
src/libostree/ostree-sysroot-deploy.c
src/libostree/ostree-types.h
tests/kolainst/destructive/soft-reboot.sh

index 367f68eaf4b8c98ba10f48cbfb5b19ded5c6d064..2319ce08ac5c3c9d71464bd5e0e03bf3d9e7cdc6 100644 (file)
@@ -68,4 +68,6 @@ void _ostree_deployment_set_overlay_initrds (OstreeDeployment *self, char **over
 
 char **_ostree_deployment_get_overlay_initrds (OstreeDeployment *self);
 
+OstreeKernelArgs *_ostree_deployment_get_kargs (OstreeDeployment *self);
+
 G_END_DECLS
index a11efe558c702f0d61be9a40098377ebeada1da5..73360d90a69a2988ef0903e49d2fcd1da77e0aff 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "config.h"
 
+#include "ostree-bootconfig-parser.h"
 #include "ostree-deployment-private.h"
 #include "ostree.h"
 #include "otutil.h"
@@ -493,3 +494,21 @@ ostree_deployment_is_soft_reboot_target (OstreeDeployment *self)
 {
   return self->soft_reboot_target;
 }
+
+/**
+ * ostree_deployment_get_kargs:
+ * @self: Deployment
+ *
+ * Returns: (transfer full) (nullable): Kernel arguments
+ */
+OstreeKernelArgs *
+_ostree_deployment_get_kargs (OstreeDeployment *self)
+{
+  OstreeBootconfigParser *bootcfg = ostree_deployment_get_bootconfig (self);
+  if (!bootcfg)
+    return NULL;
+  const char *kargs = ostree_bootconfig_parser_get (bootcfg, "options");
+  if (!kargs)
+    return NULL;
+  return ostree_kernel_args_from_string (kargs);
+}
index 7e923fe8955aea3cdaf15759a3fbe93643f140f4..afa71fb2e8ecd66534bd474080f390bf27dfbab1 100644 (file)
@@ -18,6 +18,7 @@
 #pragma once
 
 #include "ostree-bootconfig-parser.h"
+#include "ostree-types.h"
 
 G_BEGIN_DECLS
 
index 967676bb3df50f62b82a8aa00d21a804ad91e2b4..56fb3c80bf73f564cfc997a4df854e2e482948a2 100644 (file)
@@ -41,4 +41,6 @@ OstreeKernelArgsEntry *_ostree_kernel_args_entry_new (void);
 
 void _ostree_kernel_args_entry_value_free (OstreeKernelArgsEntry *e);
 
+gboolean _ostree_kernel_args_equal (OstreeKernelArgs *a, OstreeKernelArgs *b);
+
 G_END_DECLS
index 57357a30f8e93459bad415d46245ee8e1eee2701..0d9973da9ae480c850ab2efbf07b81a9cd73c18c 100644 (file)
@@ -902,3 +902,24 @@ ostree_kernel_args_delete_if_present (OstreeKernelArgs *kargs, const char *arg,
     return ostree_kernel_args_delete (kargs, arg, error);
   return TRUE;
 }
+
+gboolean
+_ostree_kernel_args_equal (OstreeKernelArgs *a, OstreeKernelArgs *b)
+{
+  if (a == b)
+    return TRUE;
+  if (a == NULL || b == NULL)
+    return FALSE;
+  if (a->order->len != b->order->len)
+    return FALSE;
+  for (guint i = 0; i < a->order->len; i++)
+    {
+      OstreeKernelArgsEntry *entry_a = g_ptr_array_index (a->order, i);
+      OstreeKernelArgsEntry *entry_b = g_ptr_array_index (b->order, i);
+      if (!g_str_equal (entry_a->key, entry_b->key))
+        return FALSE;
+      if (g_strcmp0 (entry_a->value, entry_b->value) != 0)
+        return FALSE;
+    }
+  return TRUE;
+}
index b39dafd242674342280523bff86bcd7fb1da70f6..7f5569c7ba3c59336deca2a55b1afdbcfa3108c0 100644 (file)
@@ -24,8 +24,6 @@
 
 G_BEGIN_DECLS
 
-typedef struct _OstreeKernelArgs OstreeKernelArgs;
-
 _OSTREE_PUBLIC
 void ostree_kernel_args_free (OstreeKernelArgs *kargs);
 
index 98d296a2900d97d61c9fe8e8185ac6d01dba9992..f2edef8ec9ae41d56de481f81f35eb45b7e52424 100644 (file)
@@ -39,6 +39,7 @@
 #include "libglnx.h"
 #include "ostree-core-private.h"
 #include "ostree-deployment-private.h"
+#include "ostree-kernel-args-private.h"
 #include "ostree-linuxfsutil.h"
 #include "ostree-repo-private.h"
 #include "ostree-sepolicy-private.h"
@@ -4369,13 +4370,27 @@ gboolean
 ostree_sysroot_deployment_can_soft_reboot (OstreeSysroot *self, OstreeDeployment *deployment)
 {
   OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (self);
-  if (booted_deployment != NULL)
-    {
-      const char *booted_bootcsum = ostree_deployment_get_bootcsum (booted_deployment);
-      const char *target_bootcsum = ostree_deployment_get_bootcsum (deployment);
-      return g_str_equal (booted_bootcsum, target_bootcsum);
-    }
-  return false;
+  if (booted_deployment == NULL)
+    return FALSE;
+
+  const char *booted_bootcsum = ostree_deployment_get_bootcsum (booted_deployment);
+  const char *target_bootcsum = ostree_deployment_get_bootcsum (deployment);
+  if (!g_str_equal (booted_bootcsum, target_bootcsum))
+    return FALSE;
+
+  g_autoptr (OstreeKernelArgs) booted_kargs = _ostree_deployment_get_kargs (booted_deployment);
+  g_assert (booted_kargs);
+
+  g_autoptr (OstreeKernelArgs) target_kargs = _ostree_deployment_get_kargs (deployment);
+  // The target kargs can be unset, which means use the merge kargs (same as booted, usually)
+  if (!target_kargs)
+    return TRUE;
+
+  // Compare kargs without the ostree= entry, as that will vary per bootlink even for
+  // the same boot checksum.
+  g_assert (ostree_kernel_args_delete (booted_kargs, "ostree", NULL));
+  g_assert (ostree_kernel_args_delete (target_kargs, "ostree", NULL));
+  return _ostree_kernel_args_equal (booted_kargs, target_kargs);
 }
 
 static void
index f3ba829c17b8b2173252a8d5fccfc9c2f2b3d397..4a44db0eb7a40edc61cf9752aea02a72a73a5995 100644 (file)
@@ -38,5 +38,6 @@ typedef struct OstreeMutableTree OstreeMutableTree;
 typedef struct OstreeRepoFile OstreeRepoFile;
 typedef struct _OstreeContentWriter OstreeContentWriter;
 typedef struct OstreeRemote OstreeRemote;
+typedef struct _OstreeKernelArgs OstreeKernelArgs;
 
 G_END_DECLS
index f5b23d48232b7db7dfea8b5e302df6f3d9271e45..f7b26b900e8d7b201083c754643dead83141346f 100755 (executable)
@@ -146,6 +146,15 @@ case "${AUTOPKGTEST_REBOOT_MARK:-}" in
     fatal "soft reboot prep with kernel change"
   fi
   assert_file_has_content_literal err.txt "different kernel state"
+  rm -vf err.txt
+
+  rpm-ostree cleanup -p
+
+  rpm-ostree kargs --append=foo=bar
+  if ostree admin prepare-soft-reboot 0 2>err.txt; then
+    fatal "soft reboot prep with kernel args change"
+  fi
+  assert_file_has_content_literal err.txt "different kernel state"
 
   echo "ok soft reboot all tests"
   ;;